<template>
    <div class="flex">
        <div class="border fixed h-[100vh] w-[100vw]">
            <div id="leafer-view" class="w-full h-full"></div>
        </div>
        <!-- 素材或图层面板 -->
        <div class="border fixed left-0 top-0 h-[100vh] w-[300px] bg-white">
            <el-tabs class="h-full p-2">
                <el-tab-pane label="素材">
                    <el-button
                        class="mb-2"
                        v-for="item in sucaiList"
                        @click="createFromSucai(item.name)"
                        >{{ item.name }}</el-button
                    >
                    <el-button @click="console.log(boardGroup?.toJSON())"
                        >导出json</el-button
                    >
                    <el-button @click="boardSave(boardGroup?.toJSON())"
                        >保存</el-button
                    >
                </el-tab-pane>
                <el-tab-pane label="图层" class="h-full">
                    <div class="overflow-y-auto h-full">
                        <el-tree
                            default-expand-all
                            :expand-on-click-node="false"
                            v-if="tuceng"
                            :data="tuceng"
                            @node-click="handleTreeClick"
                            draggable
                            @node-drop="handleDrop"
                            :allow-drop="handleAllowDrop"
                        >
                            <template #default="{ node, data }">
                                <span
                                    class="custom-tree-node"
                                    :class="{
                                    'bg-gray-400':
                                    editorSelected.some(
                                            (item: IUI) =>
                                                item.innerId === data.innerId
                                        ),
                                }"
                                >
                                    <span>{{ node.label }} </span>
                                </span>
                            </template>
                        </el-tree>
                    </div>
                </el-tab-pane>
            </el-tabs>
        </div>
        <!-- 属性面板 -->
        <div class="border fixed right-0 top-0 h-[100vh] w-[300px] bg-white">
            <el-tabs class="h-full">
                <el-tab-pane label="属性">
                    <ItemAttr
                        :editorSelected="editorSelected"
                        :group="boardGroup"
                        @copy="copySelected"
                        @delete="deleteSelected"
                    />
                </el-tab-pane>
            </el-tabs>
        </div>
    </div>
</template>

<script setup lang="ts">
import { boardSave } from '@/apis/localhost/boardSave'
import '@leafer-in/animate'
import { Arrow } from '@leafer-in/arrow'
import '@leafer-in/editor' // 导入图形编辑器插件
import { EditorEvent } from '@leafer-in/editor'
import { Flow } from '@leafer-in/flow'
import { HTMLText } from '@leafer-in/html'
import '@leafer-in/text-editor'
import '@leafer-in/view' // 视口控制插件
import '@leafer-in/viewport' // 导入视口插件
import { App } from '@leafer-ui/core'
import type Node from 'element-plus/es/components/tree/src/model/node'
import type { NodeDropType } from 'element-plus/es/components/tree/src/tree.type'
import type { IUI } from 'leafer-ui'
import {
    Box,
    ChildEvent,
    Group,
    KeyEvent,
    Line,
    Polygon,
    Rect,
    Text,
} from 'leafer-ui'
import { DotMatrix } from 'leafer-x-dot-matrix'
import { Snap } from 'leafer-x-snap'
import { onMounted, ref, shallowRef } from 'vue'
import ItemAttr from './ItemAttr.vue'
import './proxyData'
import testJson from './test.json'

const sucaiList = [
    {
        name: '矩形',
        create: () => {
            return new Rect({
                x: 0,
                y: 0,
                width: 100,
                height: 100,
                fill: '#efeded',
                editable: true,
            })
        },
    },
    {
        name: '双向箭头',
        create: () => {
            return new Polygon({
                x: 0,
                y: 0,
                points: [
                    0, 10, 10, 0, 10, 5, 40, 5, 40, 0, 50, 10, 40, 20, 40, 15,
                    10, 15, 10, 20, 0, 10,
                ],
                fill: '#efeded',
                editable: true,
            })
        },
    },
    {
        name: '右箭头（线条）',
        create: () => {
            return new Arrow({
                width: 50,
                y: 0,
                stroke: '#000',
                endArrow: 'arrow',
                strokeWidth: 2,
                editable: true,
            })
        },
    },
    {
        name: '右箭头（镂空）',
        create: () => {
            return new Polygon({
                x: 0,
                y: 0,
                points: [0, 5, 20, 5, 20, 0, 30, 10, 20, 20, 20, 15, 0, 15],
                fill: '#efeded',
                editable: true,
            })
        },
    },
    {
        name: '自动布局',
        create: () => {
            return new Flow({
                x: 0,
                y: 0,
                stroke: '#efeded',
                // width: 100,
                // height: 100,
                editable: true,
            })
        },
    },
    {
        name: 'Box盒子',
        create: () => {
            return new Box({
                x: 0,
                y: 0,
                stroke: '#efeded',
                // width: 100,
                // height: 100,
                editable: true,
            })
        },
    },
    {
        name: '线条',
        create: () => {
            return new Line({
                points: [
                    { x: 0, y: 0 },
                    { x: 100, y: 100 },
                ],
                stroke: '#efeded',
                editable: true,
            })
        },
    },
    {
        name: '文本',
        create: () => {
            return new Text({
                text: '新文本',
                x: 0,
                y: 0,
                fill: '#000',
                editable: true,
            })
        },
    },
    {
        name: 'HTML文本',
        create: () => {
            return new HTMLText({
                text: '新文本',
                x: 0,
                y: 0,
                fill: '#000',
                editable: true,
            })
        },
    },
]

let app: App | null = null
let boardGroup: Group | null = null

interface IUiTreeItem {
    innerId: number
    tag: string
    label: string
    children: IUiTreeItem[] | null
}
const tuceng = ref<IUiTreeItem[] | null>(null)

const editorSelected = shallowRef<IUI[]>([])

const updateTucengTree = () => {
    if (!boardGroup) return
    tuceng.value = uiItemToTree(boardGroup.children)
}

const createFromSucai = (name: string) => {
    if (!boardGroup) return
    const sucai = sucaiList.find((item) => item.name === name)
    if (sucai) {
        const obj = sucai.create()
        boardGroup.add(obj)
        app?.editor.select(obj)
    }
}

const copySelected = () => {
    if (!boardGroup || !editorSelected.value) {
        return
    }

    const newSelected: IUI[] = []

    editorSelected.value.forEach((obj: IUI) => {
        if (!boardGroup) return
        const newObj = obj.clone()
        const { x = 0, y = 0 } = newObj
        newObj.x = x + 50
        newObj.y = y + 50
        boardGroup.add(newObj)
        newSelected.push(newObj)
    })

    app?.editor.select(newSelected)
    updateTucengTree()
}

const deleteSelected = () => {
    if (!boardGroup || !editorSelected.value) {
        return
    }
    editorSelected.value.forEach((obj: IUI) => {
        obj.remove()
    })
    updateTucengTree()
}

const handleTreeClick = (data: IUiTreeItem) => {
    if (!boardGroup || !app) return
    const innerId = data.innerId
    const obj = boardGroup.find(innerId)
    if (obj) {
        app.editor.select(obj)
    }
}

const handleAllowDrop = (draggingNode: Node, dropNode: Node, type: string) => {
    if (draggingNode === dropNode) return false
    if (
        type === 'inner' &&
        !['Flow', 'Group', 'Box', 'Frame'].includes(dropNode.data.tag)
    ) {
        return false
    }
    return true
}

const handleDrop = (
    draggingNode: Node,
    dropNode: Node,
    dropType: NodeDropType
) => {
    const draggingInnerId = draggingNode.data.innerId
    const dropInnerId = dropNode.data.innerId
    if (!boardGroup) return
    console.log(dropType)
    const dropObj = boardGroup.find(dropInnerId)[0]
    const draggingObj = boardGroup.find(draggingInnerId)[0]
    if (dropObj && draggingObj) {
        if (dropType === 'inner') {
            dropObj.add(draggingObj)
        } else if (dropType === 'before') {
            // dragging在drop前面
            dropObj.parent?.addBefore(draggingObj, dropObj)
        } else if (dropType === 'after') {
            // dragging在drop后面
            dropObj.parent?.addAfter(draggingObj, dropObj)
        }
    }

    updateTucengTree()
}

const uiItemToTree = (uiItem: IUI[]) => {
    const result: IUiTreeItem[] = []

    uiItem.forEach((item) => {
        const children =
            item.children && item.children.length
                ? uiItemToTree(item.children)
                : null
        let label = item.tag
        if (item.tag === 'Text' && (item as Text).text) {
            label = item.tag + ': ' + (item as Text).text!.toString()
        }
        result.push({
            innerId: item.innerId,
            tag: item.tag,
            label,
            children,
        })
    })

    return result
}

const initEditor = (appInstance: App) => {
    app = appInstance
    const dotMatrix = new DotMatrix(appInstance)
    // 启用点阵显示
    dotMatrix.enableDotMatrix(true)

    // 0,0点显示一个点
    // appInstance.tree.add(
    //     new Rect({
    //         x: 0,
    //         y: 0,
    //         width: 20,
    //         height: 20,
    //         fill: '#000',
    //     })
    // )

    setTimeout(() => {
        appInstance.tree.zoom('fit', 0, true)
    }, 1000)

    boardGroup = new Group({
        x: 0,
        y: 0,
    })

    boardGroup.add(testJson.children as unknown as IUI[])

    appInstance.tree.add(boardGroup)

    tuceng.value = uiItemToTree(boardGroup.children)

    appInstance.cursor = 'pointer'

    const snap = new Snap(appInstance, {
        snapSize: 5,
        strokeWidth: 2,
    })

    // 启用吸附功能
    snap.enable(true)

    appInstance.editor.on(EditorEvent.SELECT, (e) => {
        editorSelected.value = e.list
    })

    appInstance.on(KeyEvent.DOWN, (e) => {
        if (e.key === 'Delete') {
            deleteSelected()
        }
    })

    boardGroup.on(ChildEvent.ADD, () => {
        updateTucengTree()
    })
    boardGroup.on(ChildEvent.REMOVE, () => {
        updateTucengTree()
    })
}

onMounted(() => {
    const app = new App({
        view: 'leafer-view',
        tree: {
            type: 'design',
        },
        editor: {},
    })
    initEditor(app)
})
</script>

<style scoped></style>
